{/* Copyright 2020 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:@react-aria/tooltip';
import statelyDocs from 'docs:@react-stately/tooltip';
import {HeaderInfo, FunctionAPI, TypeContext, InterfaceType, TypeLink, PageDescription} from '@react-spectrum/docs';
import packageData from '@react-aria/tooltip/package.json';
import Anatomy from './anatomy.svg';

---
category: Overlays
keywords: [tooltip, aria]
---

# useTooltipTrigger

<PageDescription>{docs.exports.useTooltipTrigger.description}</PageDescription>

<HeaderInfo
  packageData={packageData}
  componentNames={['useTooltipTrigger', 'useTooltip']}
  sourceData={[
    {type: 'W3C', url: 'https://www.w3.org/TR/wai-aria-1.2/#tooltip'}
  ]} />

## API

<FunctionAPI function={docs.exports.useTooltipTrigger} links={docs.links} />
<FunctionAPI function={docs.exports.useTooltip} links={docs.links} />

## Features

The HTML `title` attribute can be used to create a tooltip, but it cannot be styled. Custom styled
tooltips can be hard to build in an accessible way. `useTooltipTrigger` and `useTooltip` help build
fully accessible tooltips that can be styled as needed.

* Keyboard focus management and cross browser normalization
* Hover management and cross browser normalization
* Labeling support for screen readers (aria-describedby)
* Exposed as a tooltip to assistive technology via ARIA
* Matches native tooltip behavior with delay on hover of first tooltip and no delay on subsequent tooltips.

## Anatomy

<Anatomy />

A tooltip consists of two parts: the trigger element and the tooltip itself.
Users may reveal the tooltip by hovering or focusing the trigger.

`useTooltipTrigger` returns props to be spread onto its target trigger and the tooltip:

<TypeContext.Provider value={docs.links}>
  <InterfaceType properties={docs.links[docs.exports.useTooltipTrigger.return.id].properties} />
</TypeContext.Provider>

`useTooltip` returns props to be spread onto the tooltip:

<TypeContext.Provider value={docs.links}>
  <InterfaceType properties={docs.links[docs.exports.useTooltip.return.id].properties} />
</TypeContext.Provider>

Tooltip state is managed by the <TypeLink links={statelyDocs.links} type={statelyDocs.exports.useTooltipTriggerState} />
hook in `@react-stately/tooltip`. The state object should be passed as an option to `useTooltipTrigger` and `useTooltip`.

## Example

This example implements a Tooltip that renders in an absolute position next to its target. The <TypeLink links={docs.links} type={docs.exports.useTooltip} /> hook applies the correct ARIA attributes to the tooltip, and `useTooltipTrigger` associates it to the trigger element.

Two instances of the example are rendered to demonstrate the behavior of the delay on hover. If you hover over the first button, the tooltip will be shown after a delay. Hovering over the second button shows the tooltip immediately. If you wait for a delay before hovering another element, the delay restarts.

```tsx example export=true
import {useTooltip, useTooltipTrigger} from '@react-aria/tooltip';
import {useTooltipTriggerState} from '@react-stately/tooltip';
import {mergeProps} from '@react-aria/utils';

function Tooltip({state, ...props}) {
  let {tooltipProps} = useTooltip(props, state);

  return (
    <span
      style={{
        position: 'absolute',
        left: '5px',
        top: '100%',
        maxWidth: 150,
        marginTop: '10px',
        backgroundColor: 'white',
        color: 'black',
        padding: '5px',
        border: '1px solid gray'
      }}
      {...mergeProps(props, tooltipProps)} >
      {props.children}
    </span>
  );
}

function TooltipButton(props) {
  let state = useTooltipTriggerState(props);
  let ref = React.useRef(null);

  // Get props for the trigger and its tooltip
  let {triggerProps, tooltipProps} = useTooltipTrigger(props, state, ref);

  return (
    <span style={{position: 'relative'}}>
      <button ref={ref} {...triggerProps} style={{fontSize: 18}} onClick={() => alert('Pressed button')}>{props.children}</button>
      {state.isOpen && (
        <Tooltip state={state} {...tooltipProps}>{props.tooltip}</Tooltip>
      )}
    </span>
  );
}

<TooltipButton tooltip="Edit">✏️</TooltipButton>
<TooltipButton tooltip="Delete">🚮</TooltipButton>
```

## Usage

The following examples show how to use the `TooltipButton` component created in the above example.

### Delay

Tooltips appear after a short delay when hovering the trigger, or instantly when using keyboard focus. This delay can be adjusted for hover using the `delay` prop.

```tsx example
<TooltipButton tooltip="Save" delay={0}>💾</TooltipButton>
```

### Close Delay

Tooltips disappear after a short delay when no longer hovering the trigger, or instantly when using keyboard focus. This delay can be adjusted for hover using the `closeDelay` prop.

```tsx example
<TooltipButton tooltip="Refresh" closeDelay={0}>🔄</TooltipButton>
```

### Trigger

By default, tooltips appear both on hover and on focus. The `trigger` prop can be set to `"focus"` to display the tooltip only on focus, and not on hover.

```tsx example
<TooltipButton tooltip="Burn CD" trigger="focus">💿</TooltipButton>
```

### Controlled open state

The open state of the tooltip can be controlled via the `defaultOpen` and `isOpen` props.


```tsx example
function Example() {
  let [isOpen, setOpen] = React.useState(false);

  return (
    <>
      <p>Tooltip is {isOpen ? 'showing' : 'not showing'}</p>
      <TooltipButton tooltip="Notifications" isOpen={isOpen} onOpenChange={setOpen}>📣</TooltipButton>
    </>
  );
}
```

### Disabled

The `isDisabled` prop can be provided to a TooltipTrigger to disable the tooltip, without disabling the trigger it displays on.

```tsx example
<TooltipButton tooltip="Print" isDisabled>🖨</TooltipButton>
```

## Internationalization

### RTL

In right-to-left languages, tooltips should be mirrored across trigger. Ensure that your CSS and overlay positioning (if any) accounts for this.
